Billiard Parlour
General Operation
Each game has a CUE BALL, except Billiards has two.  A cue ball may be
launched with the mouse.  This is done by placing the mouse near the ball,
pressing, then dragging out a cue line.  The ball is launched upon release
of the mouse button, with speed proportional to the dragged length of the
cue line and direction determined by the line.  No ball other than cue 
ball(s) may be shot; for Billiards the launched ball is always the one 
closest to the initial press-down point of the mouse.

Be careful not to shoot too hard - if you 'slam' a nearby object ball, you
may get a 'hop' and not hit the object solidly.  A little practice will
reveal this.  

You can arrange balls by holding down the Option key of the keyboard while
you press on, and subsequently drag, a ball.  A menu item 'Arrange Balls'
also performs this function, but must be deselected after arrangement is
complete.  
>>
A hand-cursor results whenever balls may be arranged.  Sunk 
balls deposited near the bottom of the screen can be moved back onto the 
table without recourse to the Option key or menu.

ENGLISH is invoked by selecting same on the Options menu, upon which a 
picture of the cue ball face appears to the right of the table. The white 
spot shows where the next shot will strike the cue ball.  Note two things: 
the spot reverts to the default position after each shot, and this default 
lies at the theoretical zero-english height of 7/5 radius.

The collision sounds may be turned on or off via the Options menu item
'Sound'.  Likewise, 'English' has the effect of hiding or bringing
back the English display.  This menu item does not affect the value of
English, which in any case always reverts to zero after any shot.
>>
Scoring may be performed with the 100-carrom scoring rack atop the screen.  
When using the carroms, simply drag carroms to and fro.  The TURN SCORE is always reported in the central display just below the carrom rack.  This 
is the number of balls sunk on the previous turn.  For straightforward 
turns the number will be the amount to add into the current player's 
cumulative score.  For scratches, etc. one has to carefully apply whatever 
scoring rules have been agreed upon; in such cases the central display is 
intended as a guide, not an actual score.

SCRATCHES are reported (as beeps) when the cue ball is sunk, or in
8-ball when the 8 is sunk.  For cue ball scratches, the ball is placed
in the right-hand half of the table, at an open location.  As usual the
cue ball may be moved with the Option key or the Options menu entry
'Arrange Balls'.
>>

The Games

In BILLIARDS the players alternate between the spotted and unspotted cue
balls.  A score is logged on the central display when the current cue ball
strikes the other two object balls, but only if three rails are hit
by the cue ball before the second object ball is struck.

In STRAIGHT POOL the rack is numbered consecutively from 1 through 15, and sunk balls will be deposited in numerical order.

In 8-BALL the rack has a central 8 ball, with a certain pattern of solids
and stripes surrounding, and sunk balls are deposited with solids to the
left and stripes to the right.  There are many different 'favorite' 8-Ball 
rack configurations:  the one chosen for this program guarantees a fairly 
even distribution of stripe/solid placement over a number of breaks. 
>>
In 9-BALL the rack has a central 9 ball, with a certain pattern of balls 1
through 8 surrounding.  Sunk balls are deposited in numerical order.

In SNOOKER there are fifteen unmarked balls in the rack, with numbered 
balls 2,3,4,5,6,7 in specific places.  Sunk balls are deposited in two 
groups: numbered and unmarked.

In SLOP there are optional rack sizes, and all object balls are unmarked. 

The LAG game simply automates the 'lagging' process in which players 
alternately launch a cue ball to see who can come closer to a point or 
rail.  As with other options, players may choose their own lag criteria, 
with the program providing decision aid - in this case a lag line is drawn 
on the screen to indicate final cue ball position.  The lag also has the 
feature that the cue ball may be either dragged or shot while the item is 
checked.  NOTE: This item must be deselected to enable any other game.
>>


The Racks

The menu items 'Complete Rack' and 'Continuation Rack' provide means for
setting up games.  'Complete Rack' is used to start afresh.  'Continuation
Rack' makes the most sense in Straight Pool variations, by racking all but
the final ball left on the table.  If the number of object balls left is 
less than or greater than one, or if the single ball left is within the 
15-ball racking triangle the Complete Rack results as a default.
>>
Magnification

This is to aid in reading ball numbers and assessing complex positions.

  Glass:  A rectangle will follow the mouse movements.  Hold down the
          mouse button to magnify the selected area.  An <Option>-Click
          or a Double-click will cause the magnifying glass to disappear.
  FullScreen:  The table is blown up to greater than full-screen size.  
          Drag the mouse, with the button held down, to scroll the 
          full screen display (as in MacPaint 'ShowPage' mode). An 
          <Option>-Click or a Double-click will cause the screen
          to revert to normal.


Note:  The startup display (with animated Billiard Parlour scene) may be
       speeded up by holding down the <Option> key.
~~

Origins of Billiard Parlour

The project was started as a sharp test of Rascal animation.  We had
worked out fast 'integer calculus' routines for colliding bodies and
performing various rapid graphics functions. These formulas and techniques
coupled with bit-copying of ball images formed the basis for
the reasonably realistic billiard effects.  The final application was thus
written entirely within the Rascal compiler/development system 
environment.

The following technical remarks may be of interest to the serious 
programmer.
>>
Perhaps the most salient fact about the billiards algorithms is that no
floating point is used whatsoever.  All calculations are done in 16-bit
integer format.  The reason, of course, is the quest for speed.  Though
floating point variables are easier to work with for dynamical problems,
there is no hope for full pool table dynamics on the Macintosh unless
integer calculations predominate.
>>
The speed of the integer dynamical routines should be evident from a
consideration of what must be done to iterate an entire ensemble of hard
spheres.  Say there are N spheres total in motion on the table.  One must
on every pass of the main iteration loop

     1) Update 2N coordinate values.
     2) Update 2N velocity values.
     3) Seek and analyze collisions, requiring N*N/2 checks.
     4) Handle damping and English.
     5) For most games, check for pocket sinking for each of the N balls.
     6) Check for rail bounces for each of N balls.
     
Naturally, some of the above are interrelated - for example collision and
damping are what imply the need for updating velocities.  The fact that
N*N/2 checks are used to seek all collisions is especially cumbersome when
the number N in the ensemble is large.  For a full pool table, this means
128 checks for collisions are made at each iteration.
>>
An example of trickery intended to optimize speed is that used to check 
for collisions.  The Rascal source has a collision algorithm essentially 
like so:

     s := 4*radius*radius;
     loop(,i:=0,++i,i>numballs-1)
     {
       loop(i<numballs-1, j:=i+1, ++j, j>numballs-1)
       {
           dx := x[i] - x[j];
           if dx*dx <= s then
              { dy:= y[i] - y[j];
                if dx*dx + dy*dy <= s then
                   collide(i,j);
              };
       };
     };
 

The two loops are straightforward, dictating that we are checking for
pair (i,j) collisions where i is not equal to j.  But the primary point is 
that the check dx*dx<s is made first to save time.  Note that two balls 
have collided (that is, penetrate each other) whenever

    sqrt(dx*dx + dy*dy) <= 2*radius
    
so collision also implies sqrt(dx*dx)< 2*radius.  The 'sqrt' function can
be dropped, as in the explicit loop above, in the interest of speed.

Many such integer calculations were necessary to achieve a certain 
realism.  
>>
Other examples which might interest the programmer are:

     1) Each ball has two pictures, which alternate after every multiple
        of pi*radius is moved on the screen.  This gives an impression of
        rolling.
     2) Damping is hard to accomplish with integers.  The primary problem
        is that if we attempt at each iteration something like:        
              vx[i]:= (vx[i]*999)/1000;
              vy[i]:= (vy[i]*999)/1000;              
        then, in general, one of vx or vy will vanish completely before 
        the other, at the tail end of a ball's motion.  This causes 
        swerving at the end of the trajectory, as a ball disappointingly 
        follows one axis or the other.  The solution was to apply the 
        formula only at certain times - not in each iteration - and make 
        sure that total damping is achieved before the final swerve.  This 
        last effect is done by simply stopping the motion after a certain 
        iteration count which depends in turn on the game played and on 
        other conditions.
>>
     3) The difficulty with integer calculus is evident when one considers
        the basic Newtonian iteration:
        
             x[i]:= x[i] + vx[i];
             y[i]:= y[i] + vy[i];
             
        noting that in real-number calculus one would have each velocity
        term multiplied by a small time increment dt.  Because we cannot
        do this with integers (the smallest increment being 1) there is
        the threat that balls will move very far at each iteration.  The
        solution is easy enough: hold all coordinates and velocities as 
        large integers, and divide by a constant only when actually 
        graphing.  Thus in Billiard Parlour the typical coordinates are on 
        the order of 10000 and divisions by 100 are typical at graph time.
>>
     4) The problem of English is a good example of a tough-sounding 
     problem which turns out to be rather trivial to solve.  For English 
     effects at a rail, we add to the reflected velocity the following 
     cross- product expression:
        
              k(omega X velocity)
              
     where omega is a unit vector normal to the plane of the table and 
     indicating angular rotation, while k is the value of (horizontal)
     English.  For vertical English at a rail, we simply add to the normal 
     reflected component Vn the quantity h*Vn where h is now the vertical 
     English.  These rules are not completely exact physically, but it is 
     easy to show that the major qualitative behavior of English at rails 
     is handled correctly with these simple calculations.  For English 
     during ball-ball encounters, the same formula are used, but relegated 
     of course to the center-of-momentum frame, where each ball sees in 
     effect the other ball as a 'rail'.
>>
     5) Billiard Parlour dynamical calculations are not exact, and for the
        sake of speed some 'molecular' effects - in which balls stick 
        together momentarily - have been left in.  These effects occur 
        primarily because of the ambiguity between incoming and outgoing 
        collisions: if two balls mutually penetrate, it is not easy to 
        find out whether they have just had their velocities reflected, or 
        whether now is the time to so reflect.  The ambiguity is 
        especially fierce when many balls are banging around in a clutch.  
        So the application was designed for speed: there is a molecule 
        from time to time, but the molecule does not stay together.  
        Removing all unrealistic effects proves to take too much compute 
        time away from the otherwise pleasing motion.
>>
The serious programmer may also be interested in the various utilities and
methods unrelated to dynamics that went into the project.  The 
magnification feature for reading balls and positions easily is a good 
example of Rascal off-screen port graphics.  The sound of ball clicks is 
achieved by free-form synthesis of 'chirp' waves - i.e. high-frequency, 
brief tone bursts.  The graphics problem presented by the carroms scoring 
rack is surprisingly difficult, and stands as a good example of straight 
quickdraw methods.

The key graphics procedures are found on the standard Rascal Jan 1986
release as library entries.  The key library is called __GraphUtils, and
has many things from screen initialization to high-speed sine, cosine, and
square root functions; in general integer techniques for fast graphics.
But other libraries are involved heavily - the interested programmer can
consult the Billiard Parlour source listing in conjunction with the Rascal
User Manual.
